package logic;

import java.util.List;
import java.util.LinkedList;

public class SintaxRule{
    private List<Production> productions;
    private String id;
    private String type;
    private int position;

    public SintaxRule (){
		this.productions=new LinkedList<Production>();
		this.id="";
		this.type="";
		this.position=-1;
    }
    
    public SintaxRule(String id){
		this.id=id;
		this.productions=new LinkedList<Production>();
		this.type="";
		this.position=-1;
    }
    
    public SintaxRule(String id, List<Production> productions){
		this.id=id;
		this.productions=productions;
		this.type="";
		this.position=-1;
    }
    
    public List<Production> getProduction(){
    	return this.productions;
    }

    public String getId(){
    	return this.id;
    }

    public void addProduction(Production p){
    	this.productions.add(p);
    }

    public void setId(String id){
    	this.id=id;
    }

    public void setType(String type){
    	this.type=type;
    }
    
    public String getType(){
	return this.type;
    }

    public void setPosition(int position){
    	this.position=position;
    }
    
    public int getPosition(){
    	return this.position;
    }
    
    public boolean isThereNonConflictingProduction(){
    	boolean b=false;
    	for(int i=0;i<productions.size();i++)
    		if(!productions.get(i).isEmpty() && !productions.get(i).contains(getId()))
    			b=true;
    	return b;
    }
    
    public boolean isThereEmptyProduction(){
    	boolean b=false;
    	for(int i=0;i<productions.size();i++)
    		if(productions.get(i).isEmpty())
    			b=true;
    	return b;
    }
    
    public SintaxRule clone(){
    	SintaxRule sr=new SintaxRule();
    	for(int i=0;i<this.getProduction().size();i++)
    		sr.addProduction(this.getProduction().get(i).clone());
    	sr.setId(this.getId());
    	sr.setPosition(this.getPosition());
    	sr.setType(this.getType());
    	
    	return sr;
    }

    public String getConway(String nodo1, String nodo2){
		String conway="";
		conway+="node"+position+"in [shape=point];\n";
		conway+="node"+position+"out [shape=point];\n";
		if(type.equals("optional")){
		    conway+=nodo1+" -> "+nodo2+";\n";
		    conway+=nodo1+" -> node"+position+"in;\n";
		    conway+="node"+position+"out -> "+nodo2+";\n";
		}
		if(type.equals("repeated")){
		    conway+=nodo1+" -> "+nodo2+";\n";
		    conway+=nodo2+" -> node"+position+"in;\n";
		    conway+="node"+position+"out -> "+nodo1+";\n";
		}
		if(type.equals("grouped")){
		    conway+=nodo1+" -> node"+position+"in;\n";
		    conway+="node"+position+"out -> "+nodo2+";\n";
		}
	
		for(int i=0;i<productions.size();i++)
		    conway+=productions.get(i).getConway("node"+position+"in", "node"+position+"out", getPosition(), "innerSR");
	
		return conway;
    }

    
    
    /*
    public SintaxRule GLC2EBNF(){
		SintaxRule sr = new SintaxRule(getId());
		SintaxRule s;
		int index=-1;
		String position="";
		boolean recursion=false;
		Production p, innerp;
		for(int i=0;i<productions.size();i++){
		    p=new Production();
		    recursion=false;
		    for(int j=0;j<productions.get(i).getSimbols().size() && !recursion;j++){
				if(!productions.get(i).getSimbols().get(j).getValue().equals(getId())){
				    p.addSimbol(productions.get(i).getSimbols().get(j));
				}else{
					//Se borra la produccion
					p=new Production();
					
					index=productions.get(i).getSimbols().size()-j-1;
					System.out.println("index: " + index);
					if(index==0) index=1;
					else if(index==productions.get(i).getSimbols().size()-1)
						index=0;
					
					// Se insertan los simbolos de las otras producciones
					if(isThereNonConflictingProduction()){
						s=new SintaxRule();
						s.setPosition(1-index);
						s.setType("grouped");
						for(int m=0;m<productions.size();m++){
							innerp=new Production();
							if(!productions.get(m).contains(getId()))
								if(productions.get(m).isEmpty())
									s.setType("optional");
								else{
									for(int ms=0;ms<productions.get(m).getSimbols().size();ms++){
										innerp.addSimbol(productions.get(m).getSimbols().get(ms));
										//if(index>0)
											//index++;
									}
									s.addProduction(innerp);
								}
						}
						p.addSRSimbol(s);
					}
					
					//Se inserta un SintaxRule con repeticiones
				    s=new SintaxRule();
				    s.setPosition(index);
				    s.setType("repeated");
				    innerp=new Production();
				    for(int n=0;n<productions.get(i).getSimbols().size();n++)
				    	if(!productions.get(i).getSimbols().get(n).equals(sr.getId()))
				    		innerp.addSimbol(productions.get(i).getSimbols().get(n));
				    s.addProduction(innerp);
				    p.addSRSimbol(s);
					
				    recursion=true;
				}
		    }
		    if(!p.isEmpty())
		    	sr.addProduction(p);
		}
		
		//Miramos la primera produccion con repeticiones
		//index=-1;
		for(int prod=0;prod<sr.getProduction().size();prod++){
			index=-1;
			position="";
			if(sr.getProduction().get(prod).haveRepetition())
				index=prod;
			if(index!=-1){
				position=sr.getProduction().get(index).repetitionSide();
				//Se unen todas las producciones con repeticiones por el mismo sitio
				for(int prod2=0;prod2<sr.getProduction().size();prod2++)
					if(prod2!=index && sr.getProduction().get(prod2).haveRepetition())
						if(position.equals(sr.getProduction().get(prod2).repetitionSide())){
							for(int n=0;n<sr.getProduction().get(prod2).getRepSRSimbol().getProduction().size();n++)
								sr.getProduction().get(index).getRepSRSimbol().addProduction(sr.getProduction().get(prod2).getRepSRSimbol().getProduction().get(n));
							sr.getProduction().remove(prod2);
							prod2--;
						}
			}
		}
		
		//TODO Miramos si existen producciones con repeticiones por distinto lugar
		
		return sr;
    }
	*/
	
    public String toString(){
		String s="";
			
		if(id!=""){
		    s+=getId() + " = ";
		    for(int i=productions.size()-1;i>=0;i--){
			s+=productions.get(i).toString();
			if(i!=0)s+="| ";
			else s+="; ";
		    }
	
		}else{
		    String p="";
		    for(int i=productions.size()-1;i>=0;i--){
			p+=productions.get(i).toString();
			if(i!=0)p+="| ";
		    }
		    if(getType()=="optional")s+="[ "+p+"] ";
		    else if(getType()=="repeated")s+="{ "+p+"} ";
		    else if(getType()=="grouped")s+="( "+p+") ";
		}
		return s;
    }
}